#include "StateManager.h"

StateManager::StateManager(void)
{
	m_bShutdown = false;
}

StateManager::~StateManager(void)
{
	while(!m_ActiveStateStack.empty())
	{
		m_ActiveStateStack.back()->exit();
		m_ActiveStateStack.pop_back();
	}

	while(!m_States.empty())
	{
		m_States.back().state->destroy();
		m_States.pop_back();
	}
}

State *StateManager::findByName(Ogre::String stateName)
{
	std::vector<stateInfo>::iterator i;

	for(i = m_States.begin(); i != m_States.end(); i++)
	{
		if(i->name == stateName)
			return i->state;
	}

	return 0;
}

void StateManager::createState(Ogre::String stateName, State *state)
{
	stateInfo newStateInfo;
	newStateInfo.name = stateName;
	newStateInfo.state = state;
	m_States.push_back(newStateInfo);
}

void StateManager::start(State *state)
{
	changeState(state);

	OgreSK::getSingletonPtr()->m_pLog->logMessage("Start main loop...");

	double timeSinceLastFrame = 0;
	double startTime = 0;

	OgreSK::getSingletonPtr()->m_pRenderWnd->resetStatistics();

	while(!m_bShutdown)
	{
		if(OgreSK::getSingletonPtr()->m_pRenderWnd->isClosed())
			m_bShutdown = true;

		Ogre::WindowEventUtilities::messagePump();

		startTime = OgreSK::getSingletonPtr()->m_pTimer->getMillisecondsCPU();

		OgreSK::getSingletonPtr()->m_pKeyboard->capture();
		OgreSK::getSingletonPtr()->m_pMouse->capture();

		m_ActiveStateStack.back()->update(timeSinceLastFrame);

		OgreSK::getSingletonPtr()->updateOgre(timeSinceLastFrame);
		OgreSK::getSingletonPtr()->m_pRoot->renderOneFrame();

		timeSinceLastFrame = OgreSK::getSingletonPtr()->m_pTimer->getMillisecondsCPU() - startTime;
	}

	OgreSK::getSingletonPtr()->m_pLog->logMessage("Main loop stopped.");
}

void StateManager::initialise(State *state)
{
	OgreSK::getSingletonPtr()->m_pKeyboard->setEventCallback(state);
	OgreSK::getSingletonPtr()->m_pMouse->setEventCallback(state);
	OgreSK::getSingletonPtr()->m_pTrayMgr->setListener(state);

	OgreSK::getSingletonPtr()->m_pRenderWnd->resetStatistics();
}

void StateManager::changeState(State *state)
{
	if(!m_ActiveStateStack.empty())
	{
		m_ActiveStateStack.back()->exit();
		m_ActiveStateStack.pop_back();
	}

	m_ActiveStateStack.push_back(state);
	initialise(state);
	m_ActiveStateStack.back()->enter();
}

void StateManager::popState(void)
{
	if(!m_ActiveStateStack.empty())
	{
		m_ActiveStateStack.back()->exit();
		m_ActiveStateStack.pop_back();
	}

	if(!m_ActiveStateStack.empty())
	{
		OgreSK::getSingletonPtr()->m_pLog->logMessage("WARNING: ActiveStateStack is not empty at shutdown!");
		shutdown();
	}
	else
		shutdown();
}

void StateManager::shutdown(void)
{
	m_bShutdown = true;
}
